﻿/*******************************************************************************

    Units of Measure for C# applications

    Copyright (C) 2013 Marek Aniola

    This program is provided to you under the terms of the license
    as published at http://unitsofmeasure.codeplex.com/license


********************************************************************************/
using System;
using System.Globalization;

namespace Man.UnitsOfMeasure
{
	internal class HostDouble : ITypeHost<double>
	{
		public double Zero { get { return 0.0D; } }
		public double Unity { get { return 1.0D; } }

		public double Negative(double x) { return -x; }

		public double Add(double x, double y) { return x + y; }
		public double Subtract(double x, double y) { return x - y; }
		public double Multiply(double x, double y) { return x * y; }
		public double Divide(double x, double y) { return x / y; }

		public double Pow(double x, int num, int den) { return Math.Pow(x, (double)num / (double)den); }

		public bool Equal(double x, double y) { return x == y; }

		public int Compare(Quantity<double> x, Quantity<double> y)
		{
			return x.Value.CompareTo((x.Unit == y.Unit) ? y.Value : Calibrate(y, x.Unit));
		}

		public int Compare(Level<double> x, Level<double> y)
		{
			return x.Value.CompareTo((x.Unit == y.Unit) ? y.Value : Calibrate(y, x.Unit));
		}

		public double Calibrate(Quantity<double> q, Measure<double> target)
		{
			CheckDimensions(q.Unit, target);
			return (target.Scale / q.Unit.Scale) * q.Value;
		}

		public double Calibrate(Level<double> q, Measure<double> target)
		{
			CheckDimensions(q.Unit, target);
			return (target.Scale / q.Unit.Scale) * (q.Value - q.Unit.Shift) + target.Shift;
		}

		private static void CheckDimensions(Measure<double> x, Measure<double> y)
		{
			if (x.Sense != y.Sense) throw new InvalidOperationException(String.Format("Units \"{0}\" and \"{1}\" are of different dimensions.", x, y));
		}

		public bool TryParse(string input, NumberStyles style, IFormatProvider fp, out double result)
		{
			return double.TryParse(input, style, fp, out result);
		}
	}
}
